package service

import (
	"backend/internal/config"
	"backend/pkg/blockchain"
	"encoding/json"
	"fmt"
	"strconv"
	"time"

	"github.com/pkg/errors"
)

type EvidenceService struct {
	client       *blockchain.Client
	chainConfigs map[string]config.ChainConfig
}

func NewEvidenceService(client *blockchain.Client, chainConfigs map[string]config.ChainConfig) *EvidenceService {
	return &EvidenceService{
		client:       client,
		chainConfigs: chainConfigs,
	}
}

// getChainConfig 统一获取链配置
func (s *EvidenceService) getChainConfig(chainID string) (config.ChainConfig, error) {
	cfg, exists := s.chainConfigs[chainID]
	if !exists {
		return config.ChainConfig{}, fmt.Errorf("chain ID %s not configured", chainID)
	}
	return cfg, nil
}

// buildArgs 构建链码调用参数
func (s *EvidenceService) buildArgs(funcName string, params ...string) [][]byte {
	args := make([][]byte, 0, len(params)+1)
	args = append(args, []byte(funcName))
	for _, param := range params {
		args = append(args, []byte(param))
	}
	return args
}

// 处理链操作（统一错误处理和配置验证）
func (s *EvidenceService) handleChainOperation(chainID string, op func(cfg config.ChainConfig) ([]byte, error)) ([]byte, error) {
	cfg, err := s.getChainConfig(chainID)
	if err != nil {
		return nil, err
	}
	return op(cfg)
}

// -------------------- 核心业务方法 --------------------

// InitializeLedger 初始化账本
func (s *EvidenceService) InitializeLedger(chainID string) error {
	_, err := s.handleChainOperation(chainID, func(cfg config.ChainConfig) ([]byte, error) {
		args := s.buildArgs("Initialize")
		return s.client.SubmitTransaction(chainID, cfg.Chaincodes.Evidence.Name, args...)
	})
	return errors.Wrap(err, "账本初始化失败")
}

// CreateSideChainLock 创建侧链锁
func (s *EvidenceService) CreateSideChainLock(
	chainID, clientID string, seed int64, timeout int, dataHash, evidenceID string,
) (string, error) {
	resp, err := s.handleChainOperation(chainID, func(cfg config.ChainConfig) ([]byte, error) {
		args := s.buildArgs(
			"CreateSideChainLock",
			clientID,
			strconv.FormatInt(seed, 10),
			strconv.Itoa(timeout),
			dataHash,
			evidenceID,
		)
		return s.client.SubmitTransaction(chainID, cfg.Chaincodes.Evidence.Name, args...)
	})
	return string(resp), errors.Wrap(err, "创建侧链锁失败")
}

// CreateMainChainLock 创建主链锁
func (s *EvidenceService) CreateMainChainLock(
	chainID, hashValue, clientID string, timeout int,
	dataHash, evidenceData, evidenceID, sidechainChainID string,
) error {
	_, err := s.handleChainOperation(chainID, func(cfg config.ChainConfig) ([]byte, error) {
		args := s.buildArgs(
			"CreateMainChainLock",
			hashValue,
			clientID,
			strconv.Itoa(timeout),
			dataHash,
			evidenceData,
			evidenceID,
			sidechainChainID,
		)
		return s.client.SubmitTransaction(chainID, cfg.Chaincodes.Evidence.Name, args...)
	})
	return errors.Wrap(err, "创建主链锁失败")
}

// VerifyAndUnlock 验证并解锁
func (s *EvidenceService) VerifyAndUnlock(chainID, lockKey, preimage string) error {
	_, err := s.handleChainOperation(chainID, func(cfg config.ChainConfig) ([]byte, error) {
		args := s.buildArgs("VerifyAndUnlock", lockKey, preimage)
		return s.client.SubmitTransaction(chainID, cfg.Chaincodes.Evidence.Name, args...)
	})
	return errors.Wrap(err, "解锁操作失败")
}

// SubmitSideChainData 提交侧链数据
func (s *EvidenceService) SubmitSideChainData(
	chainID, dataHash, evidenceData, evidenceID string,
) error {
	_, err := s.handleChainOperation(chainID, func(cfg config.ChainConfig) ([]byte, error) {
		args := s.buildArgs(
			"SubmitSideChainData",
			dataHash,
			evidenceData,
			evidenceID,
		)
		return s.client.SubmitTransaction(chainID, cfg.Chaincodes.Evidence.Name, args...)
	})
	return errors.Wrap(err, "提交侧链数据失败")
}

// GetAllEvidences 获取所有存证记录
func (s *EvidenceService) GetAllEvidences(chainID string) ([]string, error) {
	resp, err := s.handleChainOperation(chainID, func(cfg config.ChainConfig) ([]byte, error) {
		args := s.buildArgs("GetAllEvidences")
		return s.client.Evaluate(chainID, cfg.Chaincodes.Evidence.Name, args...)
	})
	if err != nil {
		return nil, errors.Wrap(err, "查询存证记录失败")
	}

	var evidences []string
	if err := json.Unmarshal(resp, &evidences); err != nil {
		return nil, errors.Wrap(err, "解析存证记录失败")
	}
	return evidences, nil
}

// GetEvidence 获取单个存证
func (s *EvidenceService) GetEvidence(chainID, evidenceID string) (string, error) {
	resp, err := s.handleChainOperation(chainID, func(cfg config.ChainConfig) ([]byte, error) {
		args := s.buildArgs("GetEvidence", evidenceID)
		return s.client.Evaluate(chainID, cfg.Chaincodes.Evidence.Name, args...)
	})
	if err != nil {
		return "", errors.Wrapf(err, "查询存证失败 [evidence:%s]", evidenceID)
	}
	return string(resp), nil
}

// TimeoutRollback 超时回滚
func (s *EvidenceService) TimeoutRollback(chainID, lockKey string) error {
	_, err := s.handleChainOperation(chainID, func(cfg config.ChainConfig) ([]byte, error) {
		args := s.buildArgs("TimeoutRollback", lockKey)
		return s.client.SubmitTransaction(chainID, cfg.Chaincodes.Evidence.Name, args...)
	})
	return errors.Wrap(err, "超时回滚失败")
}

// ConfirmSync 确认跨链数据同步
func (s *EvidenceService) ConfirmSync(chainID, evidenceID string) error {
	_, err := s.handleChainOperation(chainID, func(cfg config.ChainConfig) ([]byte, error) {
		args := s.buildArgs("ConfirmSync", evidenceID)
		return s.client.SubmitTransaction(chainID, cfg.Chaincodes.Evidence.Name, args...)
	})
	return errors.Wrap(err, "确认同步失败")
}

// VerifyStorageProof 验证存储证明
func (s *EvidenceService) VerifyStorageProof(chainID, proofStr string) error {
	_, err := s.handleChainOperation(chainID, func(cfg config.ChainConfig) ([]byte, error) {
		args := s.buildArgs("VerifyStorageProof", proofStr)
		return s.client.SubmitTransaction(chainID, cfg.Chaincodes.Evidence.Name, args...)
	})
	return errors.Wrap(err, "验证存储证明失败")
}

// CreateStorageProof 创建存储证明
func (s *EvidenceService) CreateStorageProof(chainID, proofID, proofStr string) error {
	_, err := s.handleChainOperation(chainID, func(cfg config.ChainConfig) ([]byte, error) {
		args := s.buildArgs("CreateStorageProof", proofID, proofStr)
		return s.client.SubmitTransaction(chainID, cfg.Chaincodes.Evidence.Name, args...)
	})
	return errors.Wrap(err, "创建存储证明失败")
}

// VerifySaveStorageProof 验证并保存存储证明
func (s *EvidenceService) VerifySaveStorageProof(chainID, proofID, proofStr string) error {
	_, err := s.handleChainOperation(chainID, func(cfg config.ChainConfig) ([]byte, error) {
		args := s.buildArgs("VerifySaveStorageProof", proofID, proofStr)
		return s.client.SubmitTransaction(chainID, cfg.Chaincodes.Evidence.Name, args...)
	})
	return errors.Wrap(err, "验证保存存储证明失败")
}

// GetLockStatus 获取锁状态
func (s *EvidenceService) GetLockStatus(chainID, lockKey string) (map[string]interface{}, error) {
	resp, err := s.handleChainOperation(chainID, func(cfg config.ChainConfig) ([]byte, error) {
		args := s.buildArgs("GetLock", lockKey)
		return s.client.Evaluate(chainID, cfg.Chaincodes.Evidence.Name, args...)
	})
	if err != nil {
		return nil, errors.Wrapf(err, "查询锁状态失败 [lock:%s]", lockKey)
	}

	var lockStatus map[string]interface{}
	if err := json.Unmarshal(resp, &lockStatus); err != nil {
		return nil, errors.Wrap(err, "解析锁状态失败")
	}

	if timeout, ok := lockStatus["Timeout"].(float64); ok {
		lockStatus["RemainingSeconds"] = time.Until(
			time.UnixMilli(int64(timeout)),
		).Seconds()
	}

	return lockStatus, nil
}

// GetUnsyncedRecords 获取未同步记录
func (s *EvidenceService) GetUnsyncedRecords(
	chainID, sideChainID string,
) ([]map[string]interface{}, error) {
	// 调用链码
	resp, err := s.handleChainOperation(chainID, func(cfg config.ChainConfig) ([]byte, error) {
		// 按照合约签名顺序传递参数：sideChainID, mainChainID
		args := s.buildArgs(
			"GetUnsyncedSideChainRecords",
			sideChainID, // 第一个参数：侧链ID
			chainID,     // 第二个参数：主链ID
		)

		// 调用链码
		result, err := s.client.Evaluate(chainID, cfg.Chaincodes.Evidence.Name, args...)
		if err != nil {
			return nil, fmt.Errorf("链码调用失败: %w", err)
		}

		// 添加调试日志

		if len(result) > 0 && len(result) < 1000 { // 避免打印超长日志

		}

		return result, nil
	})

	if err != nil {
		return nil, errors.Wrapf(err, "查询未同步记录失败 [sidechain:%s]", sideChainID)
	}

	// 如果响应为空，返回空数组
	if len(resp) == 0 {

		return []map[string]interface{}{}, nil
	}

	// 尝试解析为直接返回的数组
	var records []map[string]interface{}
	if err := json.Unmarshal(resp, &records); err == nil {

		return records, nil
	}

	// 尝试解析包装响应格式
	var wrappedResponse struct {
		Records []map[string]interface{} `json:"records"`
	}

	if err := json.Unmarshal(resp, &wrappedResponse); err == nil && wrappedResponse.Records != nil {

		return wrappedResponse.Records, nil
	}

	// 尝试解析为EvidenceRecord列表
	var evidenceRecords []EvidenceRecord
	if err := json.Unmarshal(resp, &evidenceRecords); err == nil {

		// 将EvidenceRecord转换为map[string]interface{}
		for _, rec := range evidenceRecords {
			recMap, err := structToMap(rec)
			if err != nil {

				continue
			}
			records = append(records, recMap)
		}
		return records, nil
	}
	return nil, fmt.Errorf("无法解析响应数据: %s", string(resp))
}

// 辅助函数：将结构体转换为map
func structToMap(data interface{}) (map[string]interface{}, error) {
	dataBytes, err := json.Marshal(data)
	if err != nil {
		return nil, err
	}

	result := make(map[string]interface{})
	if err := json.Unmarshal(dataBytes, &result); err != nil {
		return nil, err
	}

	return result, nil
}

// GetChainStatistics 获取链统计信息
func (s *EvidenceService) GetChainStatistics(chainID string) (map[string]int, error) {
	evidences, err := s.GetAllEvidences(chainID)
	if err != nil {
		return nil, errors.Wrap(err, "获取存证记录失败")
	}

	stats := map[string]int{
		"total":          len(evidences),
		"activeLocks":    0, // 在实际应用中需要实现此统计
		"expiredRecords": 0,
	}
	return stats, nil
}

type EvidenceRecord struct {
	EvidenceID     string            `json:"EvidenceID"`
	DataHash       string            `json:"DataHash"`
	EvidenceData   string            `json:"EvidenceData"`
	Status         string            `json:"Status"`
	CreateTime     int64             `json:"CreateTime"`
	UpdateTime     int64             `json:"UpdateTime"`
	ChainID        string            `json:"ChainID"`
	AdditionalInfo map[string]string `json:"AdditionalInfo"`
}
